
import json
from datetime import datetime
import time

from decimal import Decimal

from django import http
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.ausers.models import Address
from apps.goods.models import SKU
#提交订单
from apps.orders.models import OrderInfo, OrderGoods
from utils.response_code import RETCODE

class OrderSuccessView(View):
    def get(self,request):
        context = {
            "payment_amount":request.GET.get("payment_amount"),
            "order_id":request.GET.get("order_id"),
            "pay_method":request.GET.get("pay_method"),
        }
        return render(request,"order_success.html",context)
class OrderCommitView(View):
    def post(self,request):
        #1.接收解析参数 address_id pay_method
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get("address_id")
        pay_method = json_dict.get("pay_method")
        #2.校验1.判空2.地址是否有 3.pay_method是否
        if not all([address_id,pay_method]):
            return http.HttpResponseBadRequest("参数不齐")
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.HttpResponseBadRequest("收货地址不存在")
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM["CASH"],OrderInfo.PAY_METHODS_ENUM["ALIPAY"]]:
            return http.HttpResponseBadRequest("支付方式不支持")
        user = request.user
        #3.生成唯一时间订单号
        order_id = datetime.now().strftime("%Y%m%d%H%M%S")+("%09d"%user.id)
        from django.db import transaction
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                #4.创建orderInfo这个数据  order,user,address,pay_method,freight:Deciaml(10.0)
                order = OrderInfo.objects.create(
                    order_id = order_id,
                    user=user,
                    address = address,
                    pay_method = pay_method,
                    total_count = 0,
                    total_amount = Decimal("0"),
                    freight = Decimal("10.0"),
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )
                #5.获取购物车redis数据，商品必须选中状态
                redis_client = get_redis_connection("carts")
                client_data = redis_client.hgetall(user.id)
                carts_selected_dict = {}
                for data in client_data.items():
                    sku_id = int(data[0].decode())
                    sku_dict = json.loads(data[1].decode())
                    #是否选中
                    if sku_dict["selected"]:
                        carts_selected_dict[sku_id]=sku_dict
                #6.根据购物车sku_ids获取skus商品 SKU
                sku_ids = carts_selected_dict.keys()
                # skus = SKU.objects.filter(id__in=sku_ids)
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        #原始销量和库存量

                        origin_sales = sku.sales
                        origin_stock = sku.stock
                        #7.判断sku的库存量  购买的个数count>库存量sku.stock：购买失败
                        sku_count = carts_selected_dict[sku.id]["count"]
                        if sku_count > sku.stock:
                            #事物回滚
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({"code":RETCODE.STOCKERR,"errmsg":"库存不足"})
                        #模拟资源抢夺
                        # import time
                        # time.sleep(5)
                        #8.sku库存量减少，销量增加
                        # sku.stock -= sku_count
                        # sku.sales += sku_count
                        # sku.save()
                        #使用乐观锁 更新库存量
                        new_stock = origin_stock - sku_count
                        new_sales = origin_sales + sku_count
                        result = SKU.objects.filter(id=sku_id,stock=origin_stock).update(stock=new_stock,sales=new_sales)
                        #如果下单失败  库存足够则继续下单  直到下单成功或者库存不足
                        if result == 0:
                            continue

                        #9.spu销量增加
                        sku.spu.sales += sku_count
                        sku.spu.save()

                        #11.订单商品表  创建  order,sku有关系属性
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            price=sku.price,
                            count = sku_count,
                        )
                        #10.计算该sku的总价格，总个数；
                        order.total_count += sku_count
                        order.total_amount += (sku_count*sku.price)
                        break
                    #12.累加运费  orderInfo.save()
                order.total_amount += order.freight
                order.save()
                #事物提交
                transaction.savepoint_commit(save_id)
            except Exception as e:
                #暴力回滚
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({"code":RETCODE.STOCKERR,"errmsg":"订单失败"})

            #13.清空选中购物车数据
            redis_client.hdel(user.id,*carts_selected_dict)
            #14.返回前端的响应结果
            return http.JsonResponse({"code":RETCODE.OK,"errmsg":"下单成功","order_id":order.order_id})

class OrderSettlementView(View):
    def get(self,request):
        #1.地址
        try:
            addresses = Address.objects.filter(user=request.user,is_deleted=False)
        except Exception as e:
            addresses = None
        #2.支付方式
        #3.redis购物车里面选中的商品
        redis_client = get_redis_connection("carts")
        client_data = redis_client.hgetall(request.user.id)
        carts_dict ={}
        for data in client_data.items():
            sku_id = int(data[0].decode())
            sku_dict = json.loads(data[1].decode())
            if sku_dict["selected"]:
                carts_dict[sku_id] = sku_dict
        total_count = 0
        total_amount = Decimal(0.00)
        skus = SKU.objects.filter(id__in= carts_dict.keys())
        for sku in skus:
            sku.count = carts_dict[sku.id].get("count")
            sku.amount = sku.price*sku.count
            total_count += sku.count
            total_amount += sku.amount
        freight = Decimal("10.00")
        total_price_all = total_amount + freight
        # 4.组合前端需要的数据格式
        context={
            "addresses": addresses,
            "skus":skus,
            "total_count":total_count,
            "total_amount":total_amount,
            'freight':freight,
            "payment_amount":total_price_all,
            "default_address_id":request.user.default_address_id,
        }
        return render(request,"place_order.html",context)



